﻿using System.Linq;
using Portal.Model;
using AutoMapper;
using System.Data;
using RepositoryFramework;
using System.Data.SqlClient;
using System;
using System.Collections.Generic;
using Portal.Repository.Entities;

namespace Portal.Repository
{
	/// <summary>
	/// Class <see cref="UserRepository"/> define repository of user
	/// </summary>
	public class UserRepository : GenericRepository, IUserRepository
	{
		private PortalUnitOfWork _unitOfWork;

		#region .ctor

		/// <summary>
		/// Class <see cref="UserRepository" /> constructor
		/// </summary>
		/// <param name="unitOfWork">The unit of work.</param>
		/// <exception cref="System.ArgumentNullException">connection</exception>
		public UserRepository(PortalUnitOfWork unitOfWork)
		{
			if (unitOfWork == null)
			{
				throw new ArgumentNullException("unitOfWork");
			}
			_unitOfWork = unitOfWork;
		}

		#endregion .ctor

		#region Methods

		/// <summary>
		/// Gets user by its login
		/// </summary>
		/// <param name="login"></param>
		/// <returns>User</returns>
		public IUser GetBy(string login)
		{
			if (string.IsNullOrWhiteSpace(login))
			{
				return null;
			}

			using (var command = new SqlCommand())
			{
				command.Connection = _unitOfWork.Connection;
				command.Transaction = _unitOfWork.Transaction;
				command.CommandType = CommandType.Text;
				command.CommandText = "SELECT id, login, firstname, lastname FROM [dbo].[User] WHERE login = @login ";

				command.Parameters.Add("@login", SqlDbType.VarChar);
				command.Parameters["@login"].Value = login;

				var table = ExecuteToDataTable(command, "User");
				var entity = GetEntity(table);
				return entity;
			}
		}

		/// <summary>
		/// Insert new user
		/// </summary>
		/// <param name="user"></param>
		/// <returns>User</returns>
		public IUser AddOrUpdate(IUser user)
		{
			if (user == null)
			{
				return null;
			}

			using (var command = new SqlCommand())
			{
				command.Connection = _unitOfWork.Connection;
				command.Transaction = _unitOfWork.Transaction;
				command.CommandType = CommandType.Text;
				command.CommandText = "MERGE [dbo].[User] AS ex USING (SELECT @id As ID, @login as Login, @firstname as firstname, @lastname as lastname) AS u ON ex.login = u.login WHEN MATCHED THEN UPDATE SET ex.firstname = @firstname, ex.lastname =@lastname WHEN NOT MATCHED THEN INSERT(login,firstname, lastname) VALUES(@login, @firstname, @lastname); SELECT id, login, firstname, lastname FROM [dbo].[User] WHERE login = @login ";

				command.Parameters.Add("@id", SqlDbType.Int);
				command.Parameters["@id"].Value = user.Id;

				command.Parameters.Add("@login", SqlDbType.VarChar);
				command.Parameters["@login"].Value = user.Login;

				command.Parameters.Add("@firstname", SqlDbType.VarChar);
				command.Parameters["@firstname"].Value = user.FirstName;

				command.Parameters.Add("@lastname", SqlDbType.VarChar);
				command.Parameters["@lastname"].Value = user.LastName;

				var table = ExecuteToDataTable(command, "User");
				var entity = GetEntity(table);
				return entity;
			}
		}

		public IUser GetEntity(DataTable dataTable)
		{
			var entities = GetEntities(dataTable);
			if (entities != null)
			{
				return entities.FirstOrDefault();
			}
			return null;
		}

		public IEnumerable<IUser> GetEntities(DataTable dataTable)
		{
			if (dataTable == null || dataTable.Rows.Count == 0)
			{
				return null;
			}
			var entities = Mapper.DynamicMap<IDataReader, List<User>>(dataTable.CreateDataReader());
			return entities;
		}

		#endregion Methods
	}
}